package org.cjstudio.holypoopsgrs.test;


import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.cjstudio.holypoopsgrs.model.UserProfile;
import org.cjstudio.holypoopsgrs.resource.HolyPoopsResourcesImpl;
import org.cjstudio.holypoopsgrs.server.Repository;
import org.cjstudio.holypoopsgrs.test.template.SpringAppEngineTest;
import org.cjstudio.holypoopsgrs.test.util.SampleData;
import org.cjstudio.holypoopsgrs.test.util.Stringify;
import org.cjstudio.holypoopsgrs_interface.game.model.HolyPoopsLeaderboard;
import org.cjstudio.holypoopsgrs_interface.game.model.HolyPoopsLeaderboardEntry;
import org.cjstudio.holypoopsgrs_interface.game.model.HolyPoopsPersonalRecord;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@ContextConfiguration("/testContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest3 extends SpringAppEngineTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		SpringAppEngineTest.tearDownAfterClass();

	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		SpringAppEngineTest.tearDownAfterClass();

	}

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();

	}

	@Override
	@After
	public void tearDown() throws Exception {
		super.tearDown();

	}


	@Resource
	private Repository<UserProfile> userProfileRepository = null;
	
	@Resource
	private HolyPoopsResourcesImpl holyPoopsResourcesImpl = null;

	@Test
	public void injectionTest() {
		// Assert the cached 'userProfileRepository' is injdected.
		Assert.assertNotNull(userProfileRepository);
		
		// Assert the cached 'holyPoopsResourcesImpl' is injdected.
		Assert.assertNotNull(holyPoopsResourcesImpl);
	}
	
	@Test
	public void getLeaderboardTest_success() {
		List<HolyPoopsLeaderboardEntry> entries = new ArrayList<HolyPoopsLeaderboardEntry>();
		//store sample profile
		for(int i=1; i<=100; i++) {
			UserProfile profile = SampleData.getSampleProfile(i);
			userProfileRepository.create(profile);

			if(i<=10) {
				entries.add(profile.toEntry());
			}
		}
		
		HolyPoopsLeaderboard leaderboard = holyPoopsResourcesImpl.getLeaderboard("daily", 10, "key");
		Assert.assertNotNull(leaderboard);
		System.out.println(Stringify.d(leaderboard));
		
		Assert.assertEquals(leaderboard.entries.size(), entries.size());
		for(int i=0; i<entries.size(); i++) {
			System.out.println(Stringify.d(leaderboard.entries.get(i)));
			System.out.println(Stringify.d(entries.get(i)));
			Assert.assertEquals(Stringify.d(leaderboard.entries.get(i)), Stringify.d(entries.get(i)));
		}
		
		// FIXME BUG?? conatinsAll doesn't work even every single string match does work.
		/*
		Assert.assertTrue(entries.containsAll(leaderboard.entries));
		*/
	}
	
	@Test
	public void getPersonalRecordTest_success() {
		//create a profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		HolyPoopsPersonalRecord record = profile.toPersonalRecord();
		HolyPoopsPersonalRecord storedRecord = holyPoopsResourcesImpl.getPersonalRecord(profile.udid);
		
		Assert.assertNotNull(record);
		Assert.assertNotNull(storedRecord);
		
		System.out.println(Stringify.d(record));
		System.out.println(Stringify.d(storedRecord));
		Assert.assertEquals(Stringify.d(record), Stringify.d(storedRecord));		
	}
	
	@Test
	public void setPersonalRecordTest_success1() {
		//create a profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//assume that record and storedRecord is equal (prev test case)
		HolyPoopsPersonalRecord storedRecord = holyPoopsResourcesImpl.getPersonalRecord(profile.udid);
		
		//set nothing
		HolyPoopsPersonalRecord updatedRecord = holyPoopsResourcesImpl.setPersonalRecord(profile.udid, null, null);
		
		Assert.assertNotNull(storedRecord);
		Assert.assertNotNull(updatedRecord);
		Assert.assertEquals(Stringify.d(storedRecord), Stringify.d(updatedRecord));
	}
	
	@Test
	public void setPersonalRecordTest_success2() {
		//create a profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//assume that record and storedRecord is equal (prev test case)
		HolyPoopsPersonalRecord storedRecord = holyPoopsResourcesImpl.getPersonalRecord(profile.udid);
		
		//set name only
		String new_name = "CORY JIN";
		storedRecord.name = new_name;
		HolyPoopsPersonalRecord updatedRecord = holyPoopsResourcesImpl.setPersonalRecord(profile.udid, new_name, null);
		
		Assert.assertNotNull(storedRecord);
		Assert.assertNotNull(updatedRecord);
		Assert.assertEquals(Stringify.d(storedRecord), Stringify.d(updatedRecord));
	}
	
	@Test
	public void setPersonalRecordTest_success3() {
		//create a profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//assume that record and storedRecord is equal (prev test case)
		HolyPoopsPersonalRecord storedRecord = holyPoopsResourcesImpl.getPersonalRecord(profile.udid);
		
		//set highest only
		Integer new_highest = 1000000000;
		storedRecord.highest = new_highest;
		HolyPoopsPersonalRecord updatedRecord = holyPoopsResourcesImpl.setPersonalRecord(profile.udid, null, new_highest);
		
		Assert.assertNotNull(storedRecord);
		Assert.assertNotNull(updatedRecord);
		Assert.assertEquals(Stringify.d(storedRecord), Stringify.d(updatedRecord));
	}
	
	@Test
	public void setPersonalRecordTest_success4() {
		//create a profile
		UserProfile profile = SampleData.getSampleProfile(0);
		userProfileRepository.create(profile);

		//assume that record and storedRecord is equal (prev test case)
		HolyPoopsPersonalRecord storedRecord = holyPoopsResourcesImpl.getPersonalRecord(profile.udid);
		
		//set both (not intended but...)
		String new_name = "CORY JIN";
		storedRecord.name = new_name;
		
		Integer new_highest = 1000000000;
		storedRecord.highest = new_highest;
		HolyPoopsPersonalRecord updatedRecord = holyPoopsResourcesImpl.setPersonalRecord(profile.udid, new_name, new_highest);
		
		Assert.assertNotNull(storedRecord);
		Assert.assertNotNull(updatedRecord);
		Assert.assertEquals(Stringify.d(storedRecord), Stringify.d(updatedRecord));
	}
	
}
